package com.qianniu.napi.admin.service.impl;

import akka.actor.ActorRef;
import akka.actor.Props;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.qianniu.napi.admin.entity.Account;
import com.qianniu.napi.admin.entity.AccountFlow;
import com.qianniu.napi.admin.entity.Order;
import com.qianniu.napi.admin.entity.User;
import com.qianniu.napi.admin.entity.penum.GtypeEnum;
import com.qianniu.napi.admin.entity.penum.IotypeEnum;
import com.qianniu.napi.admin.entity.penum.XftypeEnum;
import com.qianniu.napi.admin.mapper.AccountFlowMapper;
import com.qianniu.napi.admin.mapper.AccountMapper;
import com.qianniu.napi.admin.mapper.UserMapper;
import com.qianniu.napi.admin.service.IAccountService;
import com.qianniu.napi.admin.service.IOrderService;
import com.qianniu.napi.admin.service.IRedisService;
import com.qianniu.napi.admin.service.IUserService;
import com.qianniu.napi.admin.service.akka.AkkaServer;
import com.qianniu.napi.admin.service.akka.OrderActor;
import com.qianniu.napi.common.config.Constants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;

/**
 * <p>
 * 个人账务表 服务实现类
 * </p>
 *
 * @author chenxuebin
 * @since 2018-07-07
 */
@Service
public class AccountServiceImpl extends ServiceImpl<AccountMapper, Account> implements IAccountService {

    private final static Logger logger = LoggerFactory.getLogger(AccountServiceImpl.class);

    @Autowired
    UserMapper userMapper;
    @Autowired
    AccountMapper accountMapper;
    @Autowired
    AccountFlowMapper accountFlowMapper;
    @Autowired
    IUserService userService;
    @Autowired
    IRedisService redisService;
    @Autowired
    IOrderService orderService;

    //===该方法带完善
    //流水记录表
    //总价300=(券200+余额100=券200+会员余额49+赠送余额50<营销金额>）+实付1
    //af.setRealpay(oaf.getRealpay());//1
    //af.setDikou(oaf.getDikou());//200+50
    //af.setAmount(oaf.getAmount());//49
    public void addAccountFlow(Long uid, Long mid, Long mpid, BigDecimal money,
                               Boolean isconfirm, Integer fantimeType,
                               String sn, IotypeEnum iotype, XftypeEnum xftype, String remark, Long ywid) {

        Account entity = new Account();
        Account naccount = new Account();
        entity.setUid(uid);
        Account act = accountMapper.selectOne(entity);
        if (act == null) act = initAccount(uid, mid, mpid);

        AccountFlow af = new AccountFlow();
        af.setRealpay(money);
        af.setTotal(money);
        af.setOrigin(ywid == null ? "" : ywid.toString());

        af.setSn(sn);
        af.setIotype(iotype.getVal());// 个人账户出账
        af.setXftype(xftype.getVal());          // 个人消费
        if (isconfirm) {
            af.setIsConfirm(1);
            af.setConfirmDate(new Date());
        } else {
            af.setIsConfirm(-1);
        }
        af.setState(1);

        User user = redisService.getUser();
        af.setNickname(user != null ? user.getNickName() : null);
        af.setHeadimg(user != null ? user.getAvatarPic() : null);
        af.setPhone(user != null ? user.getPhone() : null);

        af.setTradetime(new Date());
        af.setCreatetime(af.getTradetime());
        af.setRemark(remark);
        af.setUid(uid);
        af.setMid(mid);
        af.setMpid(mpid);
        af.setLasttotal(act.getTotal());
        af.setLastamount(act.getAmount());
        af.insert();

        if (act == null) {
            act = initAccount(uid, mid, mpid);
            logger.info(">>>act at uid=" + uid + " not exist and sn=" + sn);
        }
        Boolean flag = false;
        int ret = 0;
        while (!flag && isconfirm) {

            Long version = act.getVersion();
            BigDecimal amount = act.getAmount();
            BigDecimal total = act.getTotal();
            BigDecimal chargeAmount = act.getChargeAmount();
            BigDecimal ljxiaofei = act.getLjxiaofei();
            BigDecimal mamount = act.getMamount();

            naccount.setTotal(total.add(af.getRealpay()).add(af.getDikou()));//getRealpay=实付+返现
            naccount.setAmount(amount.add(af.getRealpay()));                 // getRealpay=实付
            naccount.setLjxiaofei(ljxiaofei.add(af.getRealpay()));           // 【所有现金消费，都属于消费】
            naccount.setChargeAmount(chargeAmount.add(af.getRealpay()));     // 累计充值金额
            naccount.setMamount(mamount.add(af.getDikou()));

            naccount.setModifytime(new Date());
            naccount.setId(act.getId());
            naccount.setModifier(uid);
            naccount.setVersion(version + 1);


            af.setIsConfirm(1);
            af.setConfirmDate(new Date());
            af.setLasttotal(act.getTotal());
            af.setLastamount(act.getAmount());

            ret = accountMapper.update(naccount, new EntityWrapper<Account>().eq("uid", uid)
                    .eq("version", version));
            logger.debug(">>>>>>>>>>>>>>>accountService.update flag=" + flag);
            if (ret > 0) {
                logger.debug(">>>>>>>>>>>>>>>accountService.update af.getXftype()=" + af.getXftype());
                if (af.getXftype() == XftypeEnum.recharge.getVal()) {
                    // 会员充值检查
                }
                flag = true;
                logger.debug(">>>af.insertOrUpdate() flag=" + flag);
                af.insertOrUpdate();
            }

            act = accountMapper.selectOne(entity);
        }
    }

    //流水OUT记录表
    public void addAccountOutFlow(AccountFlow af) {

        Long uid = af.getUid();
        Long mid = af.getMid();
        Long mpid = af.getMpid();

        Account entity = new Account();
        Account naccount = new Account();
        entity.setUid(uid);
        Account act = accountMapper.selectOne(entity);
        if (act == null) act = initAccount(uid, mid, mpid);

        af.insert();

        if (act == null) {
            act = initAccount(uid, mid, mpid);
            logger.info(">>>act at uid=" + uid + " not exist and sn=" + af.getSn());
        }
        Boolean flag = false;
        int ret = 0;
        while (!flag) {

            act = accountMapper.selectOne(entity);
            Long version = act.getVersion();
            BigDecimal amount = act.getAmount();
            BigDecimal total = act.getTotal();

            BigDecimal withdraw = act.getWithdraw();
            BigDecimal ljxiaofei = act.getLjxiaofei();
            BigDecimal mamount = act.getMamount();
            BigDecimal fanliing = act.getFanliing();
            BigDecimal fanli = act.getFanli();
            BigDecimal unuseAmount = act.getUnuseAmount();
            BigDecimal withdrawing = act.getWithdrawing();

            // ================ 实付 余额 抵扣 ==============
            // 总价 300=(券200+余额100=券200+会员余额49+赠送余额50<营销金额>）+实付1
            //af.setRealpay(oaf.getRealpay());//1
            //af.setAmount(oaf.getAmount());//49
            //af.setDikou(oaf.getDikou());//200+50=250
            //af.mamount()=50
            //order.getDiscount()=200
            if (af.getXftype() == XftypeEnum.withdraw.getVal()) {

                naccount.setTotal(total.subtract(af.getRealpay()));
                naccount.setAmount(amount.subtract(af.getRealpay()));
                naccount.setWithdraw(withdraw.add(af.getRealpay()));

            } else if (af.getXftype() == XftypeEnum.buy.getVal() || af.getXftype() == XftypeEnum.maidan.getVal()) {

                Order order = orderService.selectOne(new EntityWrapper<Order>().eq("order_no",af.getSn()));
                //实际抵扣差额【区别会员充值赠送的钱，赠送的钱实际是营销金额】
                BigDecimal chae = af.getDikou().subtract(order.getDiscount());//余额=抵扣总额-折扣额=250-200=50

                naccount.setTotal(total.subtract(af.getAmount()).subtract(chae));//49+50
                naccount.setAmount(amount.subtract(af.getAmount()));//49

                naccount.setLjxiaofei(ljxiaofei.add(af.getAmount()).add(af.getRealpay()));//1+49
                naccount.setMamount(mamount.subtract(chae));//50

            } else if (af.getXftype() == XftypeEnum.refundFanli.getVal()) {

                naccount.setTotal(total.subtract(af.getAmount()));
                naccount.setFanli(fanli.subtract(af.getAmount()));

            } else if (af.getXftype() == XftypeEnum.refundFanliing.getVal()) {

                naccount.setTotal(total.subtract(af.getAmount()));
                naccount.setFanliing(fanliing.subtract(af.getAmount()));
                naccount.setUnuseAmount(unuseAmount.subtract(af.getAmount()));

            } else if (af.getXftype() == XftypeEnum.withdraw.getVal()) {

                naccount.setTotal(total.subtract(af.getRealpay()));
                naccount.setAmount(amount.subtract(af.getRealpay()));
                naccount.setWithdraw(withdraw.add(af.getRealpay()));

            } else if (af.getXftype() == XftypeEnum.withdrawing.getVal()) {

                naccount.setAmount(amount.subtract(af.getRealpay()));
                naccount.setWithdrawing(withdrawing.add(af.getRealpay()));
                naccount.setUnuseAmount(unuseAmount.add(af.getRealpay()));

            } else if (af.getXftype() == XftypeEnum.sendWithdrawing.getVal()) {

                naccount.setTotal(total.subtract(af.getRealpay()));
                naccount.setWithdrawing(withdrawing.subtract(af.getRealpay()));
                naccount.setUnuseAmount(unuseAmount.subtract(af.getRealpay()));
            }

            naccount.setModifytime(new Date());
            naccount.setId(act.getId());
            naccount.setModifier(uid);
            naccount.setVersion(version + 1);

            ret = accountMapper.update(naccount, new EntityWrapper<Account>().eq("uid", uid)
                    .eq("version", version));
            logger.debug(">>>>>>>>>>>>>>>accountService.addAccountOutFlow flag=" + flag);
            if (ret > 0) {
                af.setIsConfirm(1);
                af.setRuzhang(1);
                af.setConfirmDate(new Date());
                af.setLasttotal(act.getTotal());
                af.setLastamount(act.getAmount());
                flag = true;
                af.insertOrUpdate();
            }
        }
    }

    //流水IN记录表
    public void addAccountInFlow(AccountFlow af) {

        Long uid = af.getUid();
        Long mid = af.getMid();
        Long mpid = af.getMpid();

        Account entity = new Account();
        Account naccount = new Account();
        entity.setUid(uid);
        Account act = accountMapper.selectOne(entity);
        if (act == null) act = initAccount(uid, mid, mpid);

        af.insert();

        if (act == null) {
            act = initAccount(uid, mid, mpid);
            logger.info(">>>account at uid=" + uid + " not exist and sn=" + af.getSn());
        }
        Boolean flag = false;
        int ret = 0;
        while (ret==0) {

            act = accountMapper.selectOne(entity);
            Long version = act.getVersion();
            BigDecimal amount = act.getAmount();
            BigDecimal total = act.getTotal();

            BigDecimal withdraw = act.getWithdraw();
            BigDecimal ljxiaofei = act.getLjxiaofei();
            BigDecimal mamount = act.getMamount();
            BigDecimal fanliing = act.getFanliing();
            BigDecimal fanli = act.getFanli();
            BigDecimal unuseAmount = act.getUnuseAmount();
            BigDecimal withdrawing = act.getWithdrawing();

            // ================ 实付 余额 抵扣 ==============
            // 总价 300=(券200+余额100=券200+会员余额49+赠送余额50<营销金额>）+实付1
            //af.setRealpay(oaf.getRealpay());//1
            //af.setAmount(oaf.getAmount());//49
            //af.setDikou(oaf.getDikou());//200+50=250
            //af.mamount()=50
            //order.getDiscount()=200
            if (af.getXftype() == XftypeEnum.refundWithdrawing.getVal()) {

                naccount.setAmount(amount.add(af.getRealpay()));
                naccount.setWithdrawing(withdrawing.subtract(af.getRealpay()));
                naccount.setUnuseAmount(unuseAmount.subtract(af.getRealpay()));
            }

            naccount.setModifytime(new Date());
            naccount.setId(act.getId());
            naccount.setModifier(uid);
            naccount.setVersion(version + 1);

            ret = accountMapper.update(naccount, new EntityWrapper<Account>().eq("uid", uid)
                    .eq("version", version));
            logger.debug(">>>>>>>>>>>>>>>accountService.addAccountInFlow ret=" + ret);
            if (ret > 0) {
                af.setIsConfirm(1);
                af.setRuzhang(1);
                af.setConfirmDate(new Date());
                af.setLasttotal(act.getTotal());
                af.setLastamount(act.getAmount());
                flag = true;
                af.insertOrUpdate();
            }
        }
    }

    //流水确认确认
    // ================ 实付 余额 抵扣 ==============
    // 总价 300=(券200+余额100=券200+会员余额49+赠送余额50<营销金额>）+实付1
    //af.setRealpay(oaf.getRealpay());//1
    //af.setAmount(oaf.getAmount());//49
    //af.setDikou(oaf.getDikou());//200+50=250
    //af.mamount()=50
    //order.getDiscount()=200
    public Boolean accountFlowConfirm(Order order, AccountFlow af, String transaction_id) {

        boolean flag = false;
        int cout = 0;
        Account naccount = new Account();
        Account account = new Account();
        Long uid = af.getUid();
        // 处理消费流水（消费+买单+转账）
        // 消费(累计消费变化)
        while (af != null && !flag) {
            List<Account> accounts = accountMapper.selectList(new EntityWrapper<Account>().eq("uid", uid));
            if (accounts == null || accounts.size() == 0) {
                logger.debug("------------account at uid=" + uid + " not exist and sn=" + order.getOrderNo());
                logger.debug("------------start to init account");
                account = initAccount(uid);
            } else {
                account = accounts.get(0);
            }
            if (account == null) {
                break;
            }

            af.setTransactionid(transaction_id);
            af.setIsConfirm(1);
            af.setLastamount(account.getAmount());
            af.setLasttotal(account.getTotal());
            af.setConfirmDate(new Date());

            Long version = account.getVersion();

            BigDecimal total = account.getTotal();
            BigDecimal amount = account.getAmount();
            BigDecimal mamount = account.getMamount();
            BigDecimal yajin = account.getYajin();
            BigDecimal ljxiaofei = account.getLjxiaofei();

            BigDecimal fanli = account.getFanli();
            BigDecimal fanliing = account.getFanliing();
            BigDecimal unuseAmount = account.getUnuseAmount();

            // ================ 实付 余额 抵扣 ==============
            // 总价 300=(券200+余额100=券200+会员余额49+赠送余额50<营销金额>）+实付1
            //af.setRealpay(oaf.getRealpay());//1
            //af.setAmount(oaf.getAmount());//49
            //af.setDikou(oaf.getDikou());//200+50=250
            //af.mamount()=50
            //order.getDiscount()=200

            // 用户在线购物+用户自助买单+用户线下扫码支付
            if (af.getXftype().intValue() == XftypeEnum.buy.getVal() ||
                    af.getXftype().intValue() == XftypeEnum.maidan.getVal()) {
                // 实际抵扣差额【区别会员充值赠送的钱，赠送的钱实际是营销金额】
                BigDecimal chae = af.getDikou().subtract(order.getDiscount());//余额=抵扣总额-折扣额

                naccount.setTotal(total.subtract(af.getAmount()).subtract(chae));
                naccount.setAmount(amount.subtract(af.getAmount()));

                naccount.setLjxiaofei(ljxiaofei.add(af.getAmount()).add(af.getRealpay()));
                naccount.setMamount(mamount.subtract(chae));

                if (order.getXftype().intValue() == XftypeEnum.jyajin.getVal()) {
                    naccount.setTotal(naccount.getTotal().add(af.getRealpay()));
                    naccount.setYajin(yajin.add(af.getRealpay()));
                }
                af.setRuzhang(0);
            } else if (af.getXftype().intValue() == XftypeEnum.mshoukuan.getVal()) {
                //商家收款，直接入账到可用账户
                //已废弃《改用商户独立账户体系》
                naccount.setTotal(total.add(af.getRealpay()).add(af.getAmount()));
                naccount.setAmount(amount.add(af.getRealpay()).add(af.getAmount()));
                naccount.setFanli(fanli.add(af.getRealpay()).add(af.getAmount()));
                af.setRuzhang(0);
            }  else if (af.getXftype().intValue() == XftypeEnum.ashoukuan.getVal()) {
                //盟主收款，直接入账到可用账户(优惠买单)
                naccount.setTotal(total.add(af.getAmount()));
                naccount.setAmount(amount.add(af.getAmount()));
                naccount.setFanli(fanli.add(af.getAmount()));
                af.setRuzhang(0);
                logger.debug("------------------------------------------------start to init account accountFlowConfirm");
                logger.debug("------------------------------------------------start to init account accountFlowConfirm");
            }   else if (af.getXftype().intValue() == XftypeEnum.tuijianfan.getVal()) {
                //盟主收款，直接入账到可用账户(优惠买单)
                naccount.setTotal(total.add(af.getAmount()));
                naccount.setAmount(amount.add(af.getAmount()));
                naccount.setFanli(fanli.add(af.getAmount()));
                af.setRuzhang(0);
            } else if (af.getXftype().intValue() == XftypeEnum.recharge.getVal()) {

                BigDecimal chargeAmount = account.getChargeAmount();

                //在线充值，直接入账到可用账户
                naccount.setTotal(total.add(af.getRealpay()).add(af.getDikou()));//g etRealpay=实付+返现
                naccount.setAmount(amount.add(af.getRealpay()));                 // getRealpay=实付
                naccount.setLjxiaofei(amount.add(af.getRealpay()));              // 【所有现金消费，都属于消费】
                naccount.setChargeAmount(chargeAmount.add(af.getRealpay()));     // 累计充值金额
                naccount.setMamount(mamount.add(af.getDikou()));
                af.setRuzhang(0);
            } else if (af.getXftype().intValue() == XftypeEnum.jyajin.getVal()) {

                //在线交押金
                naccount.setTotal(total.add(af.getRealpay()));//g etRealpay=实付+返现
                naccount.setYajin(yajin.add(af.getRealpay()));//g etRealpay=实付+返现
                af.setRuzhang(0);
            } else if (af.getXftype().intValue() == XftypeEnum.jiedanyongji.getVal()) {
                //在线交押金
                naccount.setTotal(total.add(af.getRealpay()));//g etRealpay=实付+返现
                naccount.setYajin(yajin.add(af.getRealpay()));//g etRealpay=实付+返现
                af.setRuzhang(0);
            } else{
                logger.error("------------------------------accountFlowConfirm unexpect af.getXftype().intValue()="+af.getXftype().intValue());
            }

            naccount.setModifytime(new Date());
            naccount.setModifier(uid);
            naccount.setVersion(version + 1);

            cout = accountMapper.update(naccount, new EntityWrapper<Account>().eq("uid", uid).eq("version", version));
            logger.info("===========Account flag=" + flag + " and cout=" + cout);
            if (cout > 0) {
                logger.debug("------------------accountFlowConfirm af="+ JSON.toJSONString(af));
                flag = true;
                af.insertOrUpdate();
                if (af.getXftype() == XftypeEnum.recharge.getVal()) {
                    //会员充值检查
                    AkkaServer.system.actorOf(Props.create(OrderActor.class))
                            .tell(Constants.AKKA_MSG_HUIYUAN_SHENGJI + "@" + uid + "@recharge" + "@" + af.getOrigin(), ActorRef.noSender());
                }
            }
        }

        return flag;
    }

    public Boolean ruzhangFromAF(AccountFlow af) {

        boolean flag = false;
        int cout = 0;
        Account naccount = new Account();
        Account account = new Account();
        Long uid = af.getUid();
        af.setId(null);
        af.setXftype(XftypeEnum.ruzhang.getVal());
        af.setXftypename(XftypeEnum.ruzhang.getName());
        af.setConfirmDate(new Date());
        af.setTradetime(new Date());
        af.insert();

        while (!flag) {
            List<Account> accounts = accountMapper.selectList(new EntityWrapper<Account>().eq("uid", uid));
            account = accounts.get(0);
            if (account == null) account = initAccount(uid);

            Long version = account.getVersion();
            BigDecimal amount = account.getAmount();
            BigDecimal fanli = account.getFanli();
            BigDecimal fanliing = account.getFanliing();

            naccount.setAmount(amount.add(af.getAmount()));
            naccount.setFanli(fanli.add(af.getAmount()));
            naccount.setFanliing(fanliing.subtract(af.getAmount()));

            cout = accountMapper.update(naccount, new EntityWrapper<Account>().eq("uid", uid).eq("version", version));
            logger.info("===========Account flag=" + flag + " and cout=" + cout);
            if (cout > 0) {
                flag = true;
            }
        }
        return flag;
    }

    public Account initAccount(Long uid) {
        User user = userService.selectById(uid);
        if (user == null) return null;
        return initAccount(uid, user.getMid(), user.getMpid());
    }

    public Account initAccount(Long uid, Long mid, Long mpid) {

        BigDecimal zero = new BigDecimal(0);

        Account act = new Account();
        act.setUid(uid);
        act.setMid(mid);
        act.setMpid(mpid);
        act.setCreatetime(new Date());
        act.setVersion(1l);
        act.setState(1);

        User user = userMapper.selectById(uid);
        act.setNickname(user != null ? user.getNickName() : null);
        act.setHeadimg(user != null ? user.getAvatarPic() : null);
        act.setPhone(user != null ? user.getPhone() : null);

        act.setTotal(zero);
        act.setAmount(zero);
        act.setUnuseAmount(zero);
        act.setFanli(zero);
        act.setFanliing(zero);
        act.setFreeze(zero);
        act.setChargeAmount(zero);
        act.setLjxiaofei(zero);
        act.setMamount(zero);
        act.setWithdraw(zero);
        act.insert();
        return act;
    }

}
